﻿using Coldairarrow.Entity.AM;
using Coldairarrow.Entity.Base_Manage;
using Coldairarrow.IBusiness;
using Coldairarrow.Util;
using EFCore.Sharding;
using LinqKit;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Coldairarrow.Business.AM
{
    public partial class AM_AssetCheckBusiness : BaseBusiness<AM_AssetCheck>, IAM_AssetCheckBusiness, ITransientDependency
    {
        readonly IOperator _operator;
        readonly IOperatorDept _opdept;
        public AM_AssetCheckBusiness(IDbAccessor db, IOperator @operator, IOperatorDept @opdept)
            : base(db)
        {
            _operator = @operator;
            _opdept = @opdept;
        }

        #region 外部接口

        public async Task<PageResult<AM_AssetCheck>> GetDataListAsync(PageInput<ConditionDTO> input)
        {
            var q = GetIQueryable();
            var where = LinqHelper.True<AM_AssetCheck>();
            var search = input.Search;

            //筛选
            if (!search.Condition.IsNullOrEmpty() && !search.Keyword.IsNullOrEmpty())
            {
                var newWhere = DynamicExpressionParser.ParseLambda<AM_AssetCheck, bool>(
                    ParsingConfig.Default, false, $@"{search.Condition}.Contains(@0)", search.Keyword);
                where = where.And(newWhere);
            }

            return await q.Where(where).GetPageResultAsync(input);
        }

        public async Task<AM_AssetCheck> GetTheDataAsync(string id)
        {
            return await GetEntityAsync(id);
        }

        public async Task AddDataAsync(AM_AssetCheck data)
        {
            await InsertAsync(data);
        }

        public async Task UpdateDataAsync(AM_AssetCheck data)
        {
            await UpdateAsync(data);
        }

        public async Task DeleteDataAsync(List<string> ids)
        {
            await DeleteAsync(ids);
        }

        #endregion

        #region 私有成员

        #endregion

        #region  PDA资产盘点

        /// <summary>
        /// 获取资产信息
        /// </summary>
        /// <param name="AssetQrCode">资产卡片二维码</param>
        /// <param name="AssetCheckQrCode">盘点单二维码</param>
        /// <returns></returns>
        public async Task<AM_AssetItemDTO> GetAssetItemDataAsync(string AssetQrCode, string AssetCheckQrCode)
        {
            int checkid = Convert.ToInt32(AssetCheckQrCode.Split(',')?[1]);

            //查询盘点单信息
            AM_AssetCheck AssetCheck = await Db.GetIQueryable<AM_AssetCheck>().Where(x => x.CheckId == checkid).FirstOrDefaultAsync();

            AM_AssetFirmOffer AssetFirmOffer = await Db.GetIQueryable<AM_AssetFirmOffer>().Where(x => x.CheckId == checkid && x.AssetQrCode == AssetQrCode).FirstOrDefaultAsync();
            if (AssetFirmOffer != null)
            {
                throw new BusException("请勿重复扫描");
            }

            Expression<Func<AM_AssetItem, AM_AssetCategory, Base_Department, Base_Department, AM_AssetItemDTO>> select = (a, b, c, d) => new AM_AssetItemDTO
            {
                AssetCategoryName = b.AssetCategory,
                AssetPositionName = c.Name,
                DeptName = d.Name
            };
            select = select.BuildExtendSelectExpre();
            var q = from a in Db.GetIQueryable<AM_AssetItem>().AsExpandable()
                    join b in Db.GetIQueryable<AM_AssetCategory>() on a.AssetCategoryId equals b.ID into ab
                    from b in ab.DefaultIfEmpty()
                    join c in Db.GetIQueryable<Base_Department>() on a.AssetPosition equals c.Id into ac
                    from c in ac.DefaultIfEmpty()
                    join d in Db.GetIQueryable<Base_Department>() on a.ResponsibleDept equals d.Id into ad
                    from d in ad.DefaultIfEmpty()
                    select @select.Invoke(a, b, c, d);
            var assetitem = await q.Where(x => x.AssetQrCode == AssetQrCode).FirstOrDefaultAsync();
            if (assetitem.ResponsibleDept != AssetCheck.DeptId)
            {
                throw new BusException("当前资产负责部门不属于本部门,请先调拨");
            }
            return assetitem;
        }

        /// <summary>
        /// PDA盘点保存
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task InsertAssetCheckDataAsync(AssetFirmOfferDTO data)
        {
            try
            {
                //盘点单Id
                int? assetcheckId = Convert.ToInt32(data.AssetCheckQrCode.Split(',')?[1]);

                //查询盘点单信息
                AM_AssetCheck AssetCheck = await Db.GetIQueryable<AM_AssetCheck>().Where(x => x.CheckId == assetcheckId).FirstOrDefaultAsync();

                //查询资产信息
                AM_AssetItem AssetItem = await Db.GetIQueryable<AM_AssetItem>().Where(x => x.AssetQrCode == data.AssetQrCode).FirstOrDefaultAsync();
                if (AssetItem != null)
                {
                    AM_AssetFirmOffer afodata = new AM_AssetFirmOffer();
                    afodata.Id = IdHelper.GetId();
                    afodata.CheckId = assetcheckId;
                    afodata.DeptId = AssetCheck.DeptId;
                    afodata.AssetId = AssetItem.ItemId;
                    afodata.AssetCode = AssetItem.AssetCode;
                    afodata.AssetName = AssetItem.AssetName;
                    afodata.AssetQrCode = data.AssetQrCode;
                    afodata.Qty = 1;
                    afodata.CreateTime = DateTime.Now;
                    afodata.CreatorId = _operator.UserId;
                    afodata.Deleted = false;

                    await Db.InsertAsync<AM_AssetFirmOffer>(afodata);
                }
                else
                {
                    throw new BusException("请检查扫描的二维码是否正确");
                }
            }
            catch (Exception ex)
            {
                throw new BusException("请检查扫描的二维码是否正确");
            }
        }

        /// <summary>
        /// 获取实际盘点明细
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PageResult<AM_AssetFirmOfferDTO>> GetAssetFirmOfferListAsync(PageInput<AssetFirmOfferConditionDTO> input)
        {
            var search = input.Search;
            int checkid = Convert.ToInt32(search.AssetCheckQrCode.Split(',')?[1]);

            Expression<Func<AM_AssetFirmOffer, AM_AssetItem, Base_Department, AM_AssetCategory, Base_Department, AM_AssetFirmOfferDTO>> select = (a, b, c, d, e) => new AM_AssetFirmOfferDTO
            {
                AssetCategoryId = b.AssetCategoryId,
                AssetCategoryName = d.AssetCategory,
                AssetPosition = b.AssetPosition,
                AssetPositionName = c.Name,
                AssetSpec = b.AssetSpec,
                DeptName = e.Name
            };
            select = select.BuildExtendSelectExpre();
            var q = from a in Db.GetIQueryable<AM_AssetFirmOffer>().AsExpandable()
                    join b in Db.GetIQueryable<AM_AssetItem>() on a.AssetQrCode equals b.AssetQrCode into ab
                    from b in ab.DefaultIfEmpty()
                    join c in Db.GetIQueryable<Base_Department>() on b.AssetPosition equals c.Id into bc
                    from c in bc.DefaultIfEmpty()
                    join d in Db.GetIQueryable<AM_AssetCategory>() on b.AssetCategoryId equals d.ID into bd
                    from d in bd.DefaultIfEmpty()
                    join e in Db.GetIQueryable<Base_Department>() on a.DeptId equals e.Id into ae
                    from e in ae.DefaultIfEmpty()
                    select @select.Invoke(a, b, c, d, e);

            q = q.Where(x => x.CheckId == checkid);
            q = q.OrderByDescending(x => x.CreateTime);
            return await q.GetPageResultAsync(input);
        }

        /// <summary>
        /// 移除实际盘点资产信息
        /// </summary>
        /// <param name="Id">实际盘点明细Id</param>
        /// <returns></returns>
        public async Task DeleteAssetFirmOfferDataAsync(string Id)
        {
            string sqlMain = @" delete from AM_AssetFirmOffer where Id='" + Id + "'";
            await Db.ExecuteSqlAsync(sqlMain);
        }

        /// <summary>
        /// 提交资产盘点
        /// </summary>
        /// <param name="AssetCheckQrCode">盘点单二维码</param>
        /// <returns></returns>
        [Transactional]
        public async Task SubmitAssetFirmOfferAsync(string AssetCheckQrCode)
        {
            //资产盘点单Id
            int checkId = Convert.ToInt32(AssetCheckQrCode.Split(',')?[1]);
            //查询盘点单信息
            AM_AssetCheck AssetCheck = await Db.GetIQueryable<AM_AssetCheck>().Where(x => x.CheckId == checkId).FirstOrDefaultAsync();
            //查询资产盘点单明细信息
            List<AM_AssetCheckItem> AssetCheckItemList = await Db.GetIQueryable<AM_AssetCheckItem>().Where(x => x.ParentId == checkId).ToListAsync();
            //查询资产盘点单实际盘点明细
            List<AM_AssetFirmOffer> AssetFirmOfferList = await Db.GetIQueryable<AM_AssetFirmOffer>().Where(x => x.CheckId == checkId).ToListAsync();
            List<AM_AssetProfitLoss> AssetProfitLossList = new List<AM_AssetProfitLoss>();
            //实际盘点数据大于盘点单数据
            if (AssetFirmOfferList.Count > AssetCheckItemList.Count)
            {
                foreach (var item in AssetFirmOfferList)
                {
                    //查询盘点单明细是否存在
                    var checkitem = AssetCheckItemList.Where(x => x.AssetQrCode == item.AssetQrCode).FirstOrDefault();
                    if (checkitem == null)
                    {
                        AM_AssetProfitLoss AssetProfitLoss = new AM_AssetProfitLoss();
                        AssetProfitLoss.Id = IdHelper.GetId();
                        AssetProfitLoss.CheckId = checkId;
                        AssetProfitLoss.DeptId = AssetCheck.DeptId;
                        AssetProfitLoss.AssetId = item.AssetId;
                        AssetProfitLoss.AssetCode = item.AssetCode;
                        AssetProfitLoss.AssetName = item.AssetName;
                        AssetProfitLoss.AssetQrCode = item.AssetQrCode;
                        AssetProfitLoss.Qty = item.Qty;
                        AssetProfitLoss.Status = 0;
                        AssetProfitLoss.CreateTime = DateTime.Now;
                        AssetProfitLoss.CreatorId = _operator.UserId;
                        AssetProfitLoss.Deleted = false;
                        AssetProfitLossList.Add(AssetProfitLoss);
                    }
                }
            }
            //盘点单数据大于实际盘点数据
            if (AssetCheckItemList.Count > AssetFirmOfferList.Count)
            {
                foreach (var item in AssetCheckItemList)
                {
                    //查询部门下资产是否存在
                    var itemdata = AssetFirmOfferList.Where(x => x.AssetQrCode == item.AssetQrCode).FirstOrDefault();
                    if (itemdata == null)
                    {
                        AM_AssetProfitLoss AssetProfitLoss = new AM_AssetProfitLoss();
                        AssetProfitLoss.Id = IdHelper.GetId();
                        AssetProfitLoss.CheckId = checkId;
                        AssetProfitLoss.DeptId = AssetCheck.DeptId;
                        AssetProfitLoss.AssetId = item.AssetItemID;
                        AssetProfitLoss.AssetCode = item.AssetCode;
                        AssetProfitLoss.AssetName = item.AssetName;
                        AssetProfitLoss.AssetQrCode = item.AssetQrCode;
                        AssetProfitLoss.Qty = Convert.ToInt32(item.Qty);
                        AssetProfitLoss.Status = 1;
                        AssetProfitLoss.CreateTime = DateTime.Now;
                        AssetProfitLoss.CreatorId = _operator.UserId;
                        AssetProfitLoss.Deleted = false;
                        AssetProfitLossList.Add(AssetProfitLoss);
                    }
                }
            }
            await Db.InsertAsync<AM_AssetProfitLoss>(AssetProfitLossList);

            string sqlMain = @"update AM_AssetCheck set Status=2 where CheckId='" + checkId + "'";
            await Db.ExecuteSqlAsync(sqlMain);
        }

        #endregion

        #region PDA资产调拨

        /// <summary>
        /// 调拨获取资产信息
        /// </summary>
        /// <param name="AssetQrCode">资产卡片二维码</param>
        /// <returns></returns>
        public async Task<AM_AssetItemDTO> GetAllocationAssetItemDataAsync(string AssetQrCode)
        {
            Expression<Func<AM_AssetItem, AM_AssetCategory, Base_Department, Base_Department, AM_AssetItemDTO>> select = (a, b, c, d) => new AM_AssetItemDTO
            {
                AssetCategoryName = b.AssetCategory,
                AssetPositionName = c.Name,
                DeptName = d.Name
            };
            select = select.BuildExtendSelectExpre();
            var q = from a in Db.GetIQueryable<AM_AssetItem>().AsExpandable()
                    join b in Db.GetIQueryable<AM_AssetCategory>() on a.AssetCategoryId equals b.ID into ab
                    from b in ab.DefaultIfEmpty()
                    join c in Db.GetIQueryable<Base_Department>() on a.AssetPosition equals c.Id into ac
                    from c in ac.DefaultIfEmpty()
                    join d in Db.GetIQueryable<Base_Department>() on a.ResponsibleDept equals d.Id into ad
                    from d in ad.DefaultIfEmpty()
                    select @select.Invoke(a, b, c, d);
            var res = await q.Where(x => x.AssetQrCode == AssetQrCode && x.IsDisposal == false && x.IsScrap == false && x.OperationStatus == 1).FirstOrDefaultAsync();
            if (res == null)
            {
                throw new BusException("请扫描正在使用的资产卡片二维码");
            }
            return res;
        }

        /// <summary>
        /// 资产调拨保存
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [Transactional]
        public async Task SaveMotionDataAsync(AllocationAssetDTO data)
        {
            Base_User userdata = await Db.GetIQueryable<Base_User>().Where(x => x.Id == _operator.UserId).FirstOrDefaultAsync();
            string DocCode = "";
            DateTime startime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-01"));
            DateTime endtime = startime.AddMonths(1).AddSeconds(-1);
            AM_Motion Motion = await Db.GetIQueryable<AM_Motion>().Where(x => x.appliyDate >= startime && x.appliyDate <= endtime).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync();
            if (Motion == null)
            {
                DocCode = "DB-" + DateTime.Now.ToString("yyyyMM") + "-00001";
            }
            else
            {
                int code = Convert.ToInt32(Motion.DocCode.Substring(Motion.DocCode.Length - 5, 5));
                string strcode = "00000" + (code + 1);
                DocCode = "DB-" + DateTime.Now.ToString("yyyyMM") + "-" + strcode.Substring(strcode.Length - 5, 5);
            }
            //获取调入位置
            var deptdata = await _opdept.GetOperatorGongChang(data.DeptId);

            List<AM_Motion> MotionList = new List<AM_Motion>();
            List<AM_MotionDetail> MotionDetailList = new List<AM_MotionDetail>();
            foreach (var item in data.AssetItemList)
            {
                AM_MotionDetail MotionDetail = new AM_MotionDetail();
                MotionDetail.DocCode = DocCode;
                MotionDetail.Original_Location = item.AssetPosition;
                MotionDetail.AssetCode = item.AssetCode;
                MotionDetail.Desnation_Location = deptdata.DetpId;
                MotionDetail.Num = item.Qty;
                MotionDetail.AssetId = item.ItemId;
                MotionDetail.AssetName = item.AssetName;
                MotionDetail.AssetQrCode = item.AssetQrCode;
                MotionDetail.CreateTime = DateTime.Now;
                MotionDetail.CreatorId = _operator.UserId;
                MotionDetail.Deleted = false;
                MotionDetailList.Add(MotionDetail);
            }

            var ResponsibleDeptdata = data.AssetItemList.GroupBy(x => new { x.ResponsibleDept }).Select(x => new { ResponsibleDept = x.Key.ResponsibleDept }).FirstOrDefault();

            AM_Motion Motions = new AM_Motion();
            Motions.appliyDate = DateTime.Now;
            Motions.Original_orgid = ResponsibleDeptdata.ResponsibleDept;
            Motions.Desnation_orgid = data.DeptId;
            Motions.UserName = userdata.RealName;
            Motions.DocCode = DocCode;
            Motions.Status = 0;
            Motions.CreateTime = DateTime.Now;
            Motions.CreatorId = _operator.UserId;
            Motions.Deleted = false;
            MotionList.Add(Motions);

            await Db.InsertAsync<AM_MotionDetail>(MotionDetailList);

            await Db.InsertAsync<AM_Motion>(MotionList);
        }

        #endregion


        #region PDA资产报废

        /// <summary>
        /// 资产报废
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [Transactional]
        public async Task SaveAssetScrapAsync(AssetScrapDTO data)
        {
            List<AM_AssetScrap> AssetScrapList = new List<AM_AssetScrap>();
            List<AM_AssetScrapDetail> AssetScrapDetailList = new List<AM_AssetScrapDetail>();

            string ScrapCode = "";
            DateTime startime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-01"));
            DateTime endtime = startime.AddMonths(1).AddSeconds(-1);
            AM_AssetScrap Scrapdata = await Db.GetIQueryable<AM_AssetScrap>().Where(x => x.ScrapDate >= startime && x.ScrapDate <= endtime).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync();
            if (Scrapdata == null)
            {
                ScrapCode = "SC-" + DateTime.Now.ToString("yyyyMM") + "-00001";
            }
            else
            {
                int code = Convert.ToInt32(Scrapdata.ScrapCode.Substring(Scrapdata.ScrapCode.Length - 5, 5));
                string strcode = "00000" + (code + 1);
                ScrapCode = "SC-" + DateTime.Now.ToString("yyyyMM") + "-" + strcode.Substring(strcode.Length - 5, 5);
            }

            string ScrapId = IdHelper.GetId();

            foreach (var item in data.AssetItemList)
            {
                AM_AssetScrapDetail asdata = new AM_AssetScrapDetail();
                asdata.Id = IdHelper.GetId();
                asdata.ParentId = ScrapId;
                asdata.AssetId = item.ItemId;
                asdata.AssetCode = item.AssetCode;
                asdata.AssetName = item.AssetName;
                asdata.AssetQrCode = item.AssetQrCode;
                asdata.Qty = item.Qty;
                asdata.AssetPosition = item.AssetPosition;
                asdata.ResponsibleDept = item.ResponsibleDept;
                asdata.CreateTime = DateTime.Now;
                asdata.CreatorId = _operator.UserId;
                asdata.Deleted = false;
                AssetScrapDetailList.Add(asdata);
            }

            var deptdata = data.AssetItemList.GroupBy(x => new { x.ResponsibleDept }).Select(x => new { ResponsibleDept = x.Key.ResponsibleDept }).FirstOrDefault();

            AM_AssetScrap AssetScrap = new AM_AssetScrap();
            AssetScrap.Id = ScrapId;
            AssetScrap.ScrapCode = ScrapCode;
            AssetScrap.ScrapDate = DateTime.Now;
            AssetScrap.DeptId = deptdata.ResponsibleDept;
            AssetScrap.ScrapRemarks = data.ScrapRemarks;
            AssetScrap.Status = 0;
            AssetScrap.CreateTime = DateTime.Now;
            AssetScrap.CreatorId = _operator.UserId;
            AssetScrap.Deleted = false;
            AssetScrapList.Add(AssetScrap);

            await Db.InsertAsync<AM_AssetScrapDetail>(AssetScrapDetailList);

            await Db.InsertAsync<AM_AssetScrap>(AssetScrapList);
        }

        #endregion

        #region PDA资产处置

        /// <summary>
        /// 资产报废
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [Transactional]
        public async Task SaveAssetDisposalAsync(AssetScrapDTO data)
        {
            List<AM_AssetDisposal> AssetDisposalList = new List<AM_AssetDisposal>();
            List<AM_AssetDisposalDetail> AssetDisposalDetailList = new List<AM_AssetDisposalDetail>();

            string ScrapCode = "";
            DateTime startime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-01"));
            DateTime endtime = startime.AddMonths(1).AddSeconds(-1);
            AM_AssetDisposal Scrapdata = await Db.GetIQueryable<AM_AssetDisposal>().Where(x => x.ScrapDate >= startime && x.ScrapDate <= endtime).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync();
            if (Scrapdata == null)
            {
                ScrapCode = "DC-" + DateTime.Now.ToString("yyyyMM") + "-00001";
            }
            else
            {
                int code = Convert.ToInt32(Scrapdata.ScrapCode.Substring(Scrapdata.ScrapCode.Length - 5, 5));
                string strcode = "00000" + (code + 1);
                ScrapCode = "DC-" + DateTime.Now.ToString("yyyyMM") + "-" + strcode.Substring(strcode.Length - 5, 5);
            }

            string ScrapId = IdHelper.GetId();

            foreach (var item in data.AssetItemList)
            {
                AM_AssetDisposalDetail asdata = new AM_AssetDisposalDetail();
                asdata.Id = IdHelper.GetId();
                asdata.ParentId = ScrapId;
                asdata.AssetId = item.ItemId;
                asdata.AssetCode = item.AssetCode;
                asdata.AssetName = item.AssetName;
                asdata.AssetQrCode = item.AssetQrCode;
                asdata.Qty = item.Qty;
                asdata.AssetPosition = item.AssetPosition;
                asdata.ResponsibleDept = item.ResponsibleDept;
                asdata.CreateTime = DateTime.Now;
                asdata.CreatorId = _operator.UserId;
                asdata.Deleted = false;
                AssetDisposalDetailList.Add(asdata);
            }

            var deptdata = data.AssetItemList.GroupBy(x => new { x.ResponsibleDept }).Select(x => new { ResponsibleDept = x.Key.ResponsibleDept }).FirstOrDefault();

            AM_AssetDisposal AssetScrap = new AM_AssetDisposal();
            AssetScrap.Id = ScrapId;
            AssetScrap.ScrapCode = ScrapCode;
            AssetScrap.ScrapDate = DateTime.Now;
            AssetScrap.DeptId = deptdata.ResponsibleDept;
            AssetScrap.ScrapRemarks = data.ScrapRemarks;
            AssetScrap.Status = 0;
            AssetScrap.CreateTime = DateTime.Now;
            AssetScrap.CreatorId = _operator.UserId;
            AssetScrap.Deleted = false;
            AssetDisposalList.Add(AssetScrap);

            await Db.InsertAsync<AM_AssetDisposalDetail>(AssetDisposalDetailList);

            await Db.InsertAsync<AM_AssetDisposal>(AssetDisposalList);
        }

        #endregion

    }
}